package com.qq.spirit;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;

import com.gargoylesoftware.htmlunit.DialogWindow;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.Page;
import com.gargoylesoftware.htmlunit.TopLevelWindow;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.WebWindow;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import com.gargoylesoftware.htmlunit.util.UrlUtils;
import com.qq.spirit.inter.IActionAfterHttpRequest;
import com.qq.spirit.model.UserData;

/**
 * 封装的http请求对象
 * 
 * @author Administrator
 * 
 */
public class HttpUtil
{
	/**
	 * 执行post请求
	 * 
	 * @param session
	 * @param url
	 * @param pList
	 * @return
	 */
	public static void doPost(String username, String url, List<NameValuePair> pList, IActionAfterHttpRequest afterReqest)
	{
		WebClient httpclient = getWebClient(username);
		String content = "";
		List<NameValuePair> headList = new ArrayList<NameValuePair>();
		try
		{
			WebRequest wr = new WebRequest(UrlUtils.toUrlSafe(url), HttpMethod.POST);
			wr.setRequestParameters(pList);
			Page p = httpclient.getPage(wr);
			content = decodeResponseContent(p.getWebResponse().getContentAsStream(), getResponseCodingType(p), "utf-8");
		} catch (Exception e)
		{
//			LoggerUtil.error(e);
		} finally
		{
			List<WebWindow> wblist = httpclient.getWebWindows();
			for(WebWindow w:wblist)
			{
				if(w instanceof DialogWindow)
				{
					((DialogWindow)w).close();
				}else if(w instanceof TopLevelWindow)
				{
					((TopLevelWindow)w).close();
				}
			}
			if (afterReqest != null)
			{
				afterReqest.call(headList, content);
			}
		}
	}

	/**
	 * 获取请求对象
	 * 
	 * @param username
	 * @return
	 */
	private static WebClient getWebClient(String username)
	{
		UserData u = UserCache.get(username);
		if (u != null)
		{
			return u.getClient();
		}

		return null;
	}

	/**
	 * 发送get请求
	 * 
	 * @param name
	 *            请求的号码
	 * @param url
	 *            请求的url
	 */
	public static void doGet(String username, String url, IActionAfterHttpRequest afterReqest)
	{
		WebClient httpclient = getWebClient(username);
		String content = "";
		List<NameValuePair> headList = new ArrayList<NameValuePair>();
		try
		{
			Page p = httpclient.getPage(url);
			headList = p.getWebResponse().getResponseHeaders();
			content = decodeResponseContent(p.getWebResponse().getContentAsStream(), getResponseCodingType(p), "utf-8");
			// 产生xml字符串
			int idx = content.indexOf("<");
			if (idx >= 0)
			{
				content = content.substring(idx);
			}
		} catch (Exception e)
		{
//			LoggerUtil.error(e);
		} finally
		{
			List<WebWindow> wblist = httpclient.getWebWindows();
			for(WebWindow w:wblist)
			{
				if(w instanceof DialogWindow)
				{
					((DialogWindow)w).close();
				}else if(w instanceof TopLevelWindow)
				{
					((TopLevelWindow)w).close();
				}
			}
			if (afterReqest != null)
			{
				afterReqest.call(headList, content);
			}
		}
	}

	/**
	 * 获取请求结果的编码类型
	 * 
	 * @param p
	 * @return
	 */
	private static String getResponseCodingType(Page p)
	{
		String ceValue = p.getWebResponse().getResponseHeaderValue("Content-Encoding") + "";
		if (ceValue.indexOf("gzip") >= 0)
		{
			return "gzip";
		}
		String ctValue = p.getWebResponse().getResponseHeaderValue("Content-Type") + "";
		if (ctValue.indexOf("x-gzip-compressed") >= 0)
		{
			return "zlib";
		}
		return "text";
	}

	public static String decodeResponse(Page p)
	{
		return decodeResponseContent(p.getWebResponse().getContentAsStream(), getResponseCodingType(p), "utf-8");
	}

	/**
	 * 解析输入类型
	 * 
	 * @param ins
	 * @param codingType
	 * @param charSet
	 * @return
	 */	
	public static String decodeResponseContent(InputStream ins, String codingType, String charSet)
	{
		if (codingType.endsWith("gzip"))
		{
			return decodeGzip(ins, charSet);
		}
		if (codingType.endsWith("zlib"))
		{
			return decodeZlib(ins, charSet);
		}
		if (codingType.endsWith("text"))
		{
			return decodeText(ins, charSet);
		}

		return decodeText(ins, charSet);
	}

	/**
	 * 解析普通的未经压缩的输入流
	 * 
	 * @param ins
	 * @param charsetName
	 * @return
	 */
	private static String decodeText(InputStream ins, String charsetName)
	{
		try
		{
			byte[] ib = new byte[1024];
			ByteArrayOutputStream oBuff = new ByteArrayOutputStream();
			int tlen = -1;
			while ((tlen = ins.read(ib)) != -1)
			{
				oBuff.write(ib, 0, tlen);
			}
			return new String(oBuff.toByteArray(), charsetName);
		} catch (IOException e)
		{
			LoggerUtil.error(e);
		}
		return "";
	}

	/**
	 * 解码gzip类型编码,默认均为utf-8编码
	 * 
	 * @param ins
	 * @return
	 */
	private static String decodeZlib(InputStream ins, String charsetName)
	{
		ByteArrayOutputStream oBuff;
		try
		{
			InflaterInputStream gis = new InflaterInputStream(ins);
			byte[] ib = new byte[1024];
			oBuff = new ByteArrayOutputStream();
			int tlen = -1;
			// 放弃前2个直接，这2个不知道干啥的，可能是标志
			// zis.read(ib,0, 2);
			while ((tlen = gis.read(ib)) != -1)
			{
				oBuff.write(ib, 0, tlen);
			}
			return new String(oBuff.toByteArray(), charsetName);
		} catch (IOException e)
		{
			LoggerUtil.error(e);
		}
		return "";
	}

	/**
	 * 解码gzip类型编码,默认均为utf-8编码
	 * 
	 * @param ins
	 * @return
	 */
	private static String decodeGzip(InputStream ins, String charsetName)
	{
		try
		{
			GZIPInputStream gis = new GZIPInputStream(ins);
			byte[] ib = new byte[1024];
			ByteArrayOutputStream oBuff = new ByteArrayOutputStream();
			int tlen = -1;
			while ((tlen = gis.read(ib)) != -1)
			{
				oBuff.write(ib, 0, tlen);
			}
			return new String(oBuff.toByteArray(), charsetName);
		} catch (IOException e)
		{
			LoggerUtil.error(e);
		}
		return "";
	}

}
